﻿using System;
using System.Runtime.InteropServices;

namespace MediaRemoteServer
{
    public class MediaItem : IDisposable, ICloneable
    {

        #region libvlc functions

        [DllImport("libvlc")]
        private static extern IntPtr libvlc_media_new(IntPtr p_libvlc_instance, string mrl, IntPtr p_e);

        [DllImport("libvlc")]
        private static extern void libvlc_media_retain(IntPtr p_m);

        [DllImport("libvlc")]
        private static extern void libvlc_media_add_option(IntPtr p_m, string options);

        [DllImport("libvlc")]
        private static extern void libvlc_media_add_option_flag(IntPtr p_m, string options, libvlc_media_option_t flags);

        [DllImport("libvlc")]
        private static extern void libvlc_media_release(IntPtr p_m);

        [DllImport("libvlc")]
        private static extern string libvlc_media_get_mrl(IntPtr p_m);

        [DllImport("libvlc")]
        private static extern IntPtr libvlc_media_duplicate(IntPtr p_m);

        [DllImport("libvlc")]
        private static extern string libvlc_media_get_meta(IntPtr p_m, libvlc_meta_t meta);

        [DllImport("libvlc")]
        private static extern libvlc_state_t libvlc_media_get_state(IntPtr p_m);

        [DllImport("libvlc")]
        private static extern long libvlc_media_get_duration(IntPtr p_m, IntPtr p_e);

        [DllImport("libvlc")]
        private static extern int libvlc_media_is_preparsed(IntPtr p_m);

        #endregion

        #region libvlc data types

        public enum libvlc_media_option_t
        {
            libvlc_media_option_trusted,
            libvlc_media_option_unique,
        }

        public enum libvlc_meta_t
        {
            libvlc_meta_Title,
            libvlc_meta_Artist,
            libvlc_meta_Genre,
            libvlc_meta_Copyright,
            libvlc_meta_Album,
            libvlc_meta_TrackNumber,
            libvlc_meta_Description,
            libvlc_meta_Rating,
            libvlc_meta_Date,
            libvlc_meta_Setting,
            libvlc_meta_URL,
            libvlc_meta_Language,
            libvlc_meta_NowPlaying,
            libvlc_meta_Publisher,
            libvlc_meta_EncodedBy,
            libvlc_meta_ArtWorkURL,
            libvlc_meta_TrackID,
        }

        public enum libvlc_state_t
        {
            libvlc_NothingSpecial,
            libvlc_Opening,
            libvlc_Buffering,
            libvlc_Playing,
            libvlc_Paused,
            libvlc_Stopped,
            libvlc_Ended,
            libvlc_Error,
        }

        #endregion

        public IntPtr instance { get; private set; }
        private LibVLC libVLC;

        public MediaItem(string mrl, LibVLC libVLCInstance)
        {
            libVLC = libVLCInstance;
            libVLC.clearException();
            instance = libvlc_media_new(libVLC.instance, mrl, libVLC.pException);
        }

        public MediaItem(IntPtr mediaInstance, LibVLC libVLCInstance)
        {
            instance = mediaInstance;
            libVLC = libVLCInstance;
        }

        public void addOption(string option)
        {
            libvlc_media_add_option(instance, option);
        }

        public void addOption(string option, libvlc_media_option_t flag)
        {
            libvlc_media_add_option_flag(instance, option, flag);
        }

        public string getMRL()
        {
            return libvlc_media_get_mrl(instance);
        }

        public string getMeta(libvlc_meta_t meta)
        {
            return libvlc_media_get_meta(instance, meta);
        }

        public libvlc_state_t getState()
        {
            return libvlc_media_get_state(instance);
        }

        public long getDuration()
        {
            libVLC.clearException();
            return libvlc_media_get_duration(instance, libVLC.pException);
        }

        public bool isPreparsed()
        {
            return libvlc_media_is_preparsed(instance) != 0;
        }

        #region ICloneable Members

        public object Clone()
        {
            return new MediaItem(libvlc_media_duplicate(instance), libVLC);
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            libvlc_media_release(instance);
        }

        #endregion
    }
}
